home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MACD 5
/
MACD 5.bin
/
workbench
/
wb
/
czesc_3
/
reyes
/
reyes.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-12-31
|
31KB
|
1,215 lines
/*
* REyes
*
* A screen blanker for the Retina graphics card.
* By Michael Heinz, 8 January, 1994
*
* Main routines
*
* $Log: REyes.c $
* Revision 1.2 1994/02/07 17:44:57 mheinz
* Added RCS stuff.
*
*/
#include <exec/memory.h>
#include <exec/ports.h>
#include <exec/execbase.h>
#include <graphics/displayinfo.h>
#include <intuition/intuitionbase.h>
#include <intuition/gadgetclass.h>
#include <libraries/commodities.h>
#include <libraries/gadtools.h>
#include <dos/dosextens.h>
#include <dos/dostags.h>
#include <utility/tagitem.h>
#include <clib/alib_protos.h>
#include <clib/commodities_protos.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>
#include <clib/macros.h>
#include <clib/retina_protos.h>
#include <retina/retina.h>
#include <string.h>
#include <stdlib.h>
#include <pragmas/commodities_pragmas.h>
#include <pragmas/dos_pragmas.h>
#include <pragmas/exec_pragmas.h>
#include <pragmas/gadtools_pragmas.h>
#include <pragmas/graphics_pragmas.h>
#include <pragmas/intuition_pragmas.h>
#include <pragmas/retina_pragmas.h>
#ifdef SMALLEYES
#include "smalleyes.h"
#else
#include "retinaeyes.h"
#endif
UBYTE *VersionString = "$VER: REyes 1.3 (By Michael Heinz)";
#define NORMAL_WIDE 640
#define NORMAL_HIGH 480
#define SMALL_WIDE 320
#define SMALL_HIGH 240
void
chkabort(void)
{
}
/*
* Common Definitions
*/
extern struct ExecBase *SysBase;
extern struct DosLibrary *DOSBase;
struct IntuitionBase *IntuitionBase;
struct RetinaBase *RetinaBase;
struct Library *CxBase, *GadToolsBase, *IconBase;
#define FINDPROCPORT (&((struct Process *)SysBase->ThisTask)->pr_MsgPort)
/*
* A handy request structure for reporting that we've up and died.
*/
struct EasyStruct quitreq =
{
sizeof(struct EasyStruct),
0,
"REyes",
"REyes has suffered an untimely demise\ndue to: %s",
"OK|OK"
};
void
Error(char *s)
{
if (s) EasyRequest(NULL,&quitreq,NULL,s);
}
/*
* Definitions for our Commodity
*/
struct NewBroker NewBroker =
{NB_VERSION, "REyes ", NULL,
"Somebody's watching you...", NBU_NOTIFY | NBU_UNIQUE, COF_SHOW_HIDE,
0, NULL, 0};
struct MsgPort *CxPort;
UBYTE *PopKey;
UBYTE *BlankKey;
#define HOTKEY_OPEN_WINDOW 1L
#define HOTKEY_BLANK_SCREEN 2L
#define DEF_CX_PRI 0
#define DEF_POPKEY "control alt s"
#define DEF_BLANKKEY "lamiga s"
LONG TimeOut, ClientTimeOut;
#define MAX_TIMEOUT 3600L
#define MAX_CLIENT_TIMEOUT 60L
#define DEF_TIMEOUT 60L
#define DEF_CLIENT_TIMEOUT 5L
#define SERVER_PRI 3L
#define CLIENT_PRI -5L
/*
* Definitions for Eye Movement
*/
#define RAND(m) (Random(m)-(m)/2)
#define MAX_SPEED 10L
#define MAX_EYES 10L
#define MAX_CHANCE 100L
#define DEF_EYES 5L
#define DEF_SPEED 4L
#define DEF_CHANCE 10L
#define DEF_MODE MID_DEFAULT_08
LONG NumEyes, Speed, Chance;
typedef struct {
int NumEyes;
Eyes *Eye[MAX_EYES];
} EyeStruct;
EyeStruct EyeList;
/*
* Definitions for our configuration window
*/
struct NewWindow NewBlankerWindow =
{
80, 16, 0, 0, 0, 1,
IDCMP_CLOSEWINDOW | IDCMP_REFRESHWINDOW | IDCMP_GADGETDOWN |
IDCMP_GADGETUP | IDCMP_VANILLAKEY | SLIDERIDCMP | LISTVIEWIDCMP,
WINDOWCLOSE | WINDOWDRAG | WINDOWDEPTH | SIMPLE_REFRESH,
NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0,
WBENCHSCREEN
};
struct Window *BlankerWindow;
#define GID_HIDE 1
#define GID_BLANK 2
#define GID_QUIT 3
#define GID_TIMEOUT 4
#define GID_CLIENT 5
#define GID_EYES 6
#define GID_SPEED 7
#define GID_CHANCE 8
#ifdef SMALLEYES
#define NUM_GADS 7
#else
#define NUM_GADS 8
#endif
struct VisualInfo *BlankerVisualInfo;
struct Gadget *BlankerGadgets;
struct TextAttr BlankerAttr =
{"topaz.font", TOPAZ_EIGHTY, FS_NORMAL, FPF_ROMFONT};
struct NewGadget NewBlankerGadgets[NUM_GADS] =
{16, 101, 48, 12, "_Hide", &BlankerAttr, GID_HIDE, PLACETEXT_IN, NULL, NULL,
80, 101, 48, 12, "_Blank", &BlankerAttr, GID_BLANK, PLACETEXT_IN, NULL, NULL,
144, 101, 48, 12, "_Quit", &BlankerAttr, GID_QUIT, PLACETEXT_IN, NULL, NULL,
136, 5, 66, 12, "Timeout", &BlankerAttr, GID_TIMEOUT, PLACETEXT_LEFT, NULL, NULL,
136, 21, 66, 12, "Client Timeout", &BlankerAttr, GID_CLIENT, PLACETEXT_LEFT, NULL, NULL,
136, 53, 66, 12, "Speed ", &BlankerAttr, GID_SPEED, PLACETEXT_LEFT, NULL, NULL,
136, 69, 66, 12, "Eyes ", &BlankerAttr, GID_EYES, PLACETEXT_LEFT, NULL, NULL,
#ifndef SMALLEYES
136, 37, 66, 12, "%Anim ", &BlankerAttr, GID_CHANCE, PLACETEXT_LEFT, NULL, NULL,
#endif
};
UBYTE BlankerGadgetKinds[NUM_GADS] =
{
BUTTON_KIND, BUTTON_KIND, BUTTON_KIND, INTEGER_KIND, INTEGER_KIND, SLIDER_KIND,
SLIDER_KIND,
#ifndef SMALLEYES
SLIDER_KIND
#endif
};
struct TagItem ButtonGadgetTags[] =
{GT_Underscore, (ULONG) '_', TAG_DONE, 0L};
struct TagItem TimeGadgetTags[] =
{GTIN_Number, 0L, GTIN_MaxChars, 4L, TAG_DONE, 0L};
struct TagItem ClientGadgetTags[] =
{GTIN_Number, 0L, GTIN_MaxChars, 2L, TAG_DONE, 0L};
struct TagItem ChanceGadgetTags[] =
{GTSL_Level, 0L, GTSL_Min, 1L, GTSL_Max, MAX_CHANCE, GTSL_LevelFormat, 0L,
GTSL_LevelPlace, PLACETEXT_LEFT, GTSL_MaxLevelLen, 3L, GA_RELVERIFY, TRUE,
TAG_DONE, 0L};
struct TagItem SpeedGadgetTags[] =
{GTSL_Level, 0L, GTSL_Min, 1L, GTSL_Max, MAX_SPEED, GTSL_LevelFormat, 0L,
GTSL_LevelPlace, PLACETEXT_LEFT, GTSL_MaxLevelLen, 2L, GA_RELVERIFY, TRUE,
TAG_DONE, 0L};
struct TagItem EyesGadgetTags[] =
{GTSL_Level, 0L, GTSL_Min, 1L, GTSL_Max, MAX_EYES, GTSL_LevelFormat, 0L,
GTSL_LevelPlace, PLACETEXT_LEFT, GTSL_MaxLevelLen, 2L, GA_RELVERIFY, TRUE,
TAG_DONE, 0L};
struct TagItem *BlankerGadgetTagLists[NUM_GADS] =
{
&ButtonGadgetTags[0],
&ButtonGadgetTags[0],
&ButtonGadgetTags[0],
&TimeGadgetTags[0],
&ClientGadgetTags[0],
&SpeedGadgetTags[0],
&EyesGadgetTags[0],
#ifndef SMALLEYES
&ChanceGadgetTags[0],
#endif
};
/*
* Definitions for Server/Client Communication
*/
BYTE bsp_TimerSig, bsp_InputSig, bsp_ClientSig;
struct Task *ServerProcess;
#define MASK(n) (1L<<(n))
struct ClientMessage {
struct Message bcm_Message;
struct RetinaScreen *bcm_Screen;
LONG bcm_Status;
ULONG bcm_SigMask;
LONG bcm_Eyes, bcm_Speed, bcm_Chance;
};
/*
* The following functions are used to track resources.
*/
struct ToolNode {
struct ToolNode *Next;
void *Tool;
void (*RemProc) (void *, LONG);
LONG Size;
}
*ToolList;
void __regargs
RemTool(void *Tool)
{
struct ToolNode *Ptr, *OPtr;
Ptr = ToolList;
OPtr = NULL;
while (Ptr) {
if (Ptr->Tool==Tool) {
Ptr->RemProc(Ptr->Tool,Ptr->Size);
if (OPtr)
OPtr->Next=Ptr->Next;
else
ToolList=Ptr->Next;
FreeMem(Ptr,sizeof(struct ToolNode));
return;
} else {
OPtr=Ptr;
Ptr=Ptr->Next;
}
}
}
void __regargs
Quit(int ReturnCode, char *s)
{
while (ToolList)
RemTool(ToolList->Tool);
if (ReturnCode) Error(s);
exit(ReturnCode);
}
void __regargs
AddTool(void *NewTool, void *ProcPtr, LONG NewSize, char *errmsg)
{
struct ToolNode *Ptr;
void (*NewRemProc) (void *, LONG);
NewRemProc = ProcPtr;
if (NewTool == NULL)
Quit(10,errmsg);
if ((Ptr = AllocMem(sizeof(struct ToolNode), MEMF_CLEAR)) == NULL) {
NewRemProc(NewTool, NewSize);
Quit(20,"Out of Memory.");
}
Ptr->Next = ToolList;
Ptr->Tool = NewTool;
Ptr->RemProc = NewRemProc;
Ptr->Size = NewSize;
ToolList = Ptr;
}
/*
* Some utility functions
*/
void __stdargs
DeleteMsgPortSafely(struct MsgPort *AnyPort)
{
struct Message *AnyMsg;
while (AnyMsg = GetMsg(AnyPort))
ReplyMsg(AnyMsg);
DeleteMsgPort(AnyPort);
}
int __regargs
ArgIntMax(char **ToolTypes, char *ID, int Default, int Max)
{
int Val;
Val = ArgInt(ToolTypes, ID, Default);
if ((Val < 1) || (Val > Max))
return Default;
else
return Val;
}
/*
* The "InputHandler". It signals the server process
* when an input or timer event is received.
*/
void __interrupt __saveds
BlankerAction(CxMsg * CxMsg, CxObj * CO)
{
struct InputEvent *IE;
IE = (struct InputEvent *)CxMsgData(CxMsg);
if (IE->ie_Class == IECLASS_TIMER)
Signal(ServerProcess, 1L << bsp_TimerSig);
else
Signal(ServerProcess, 1L << bsp_InputSig);
}
/*
* Functions for Handling the Configuration Window
*/
LONG
GetNum(struct Gadget *Gadget, LONG * Data, LONG Max)
{
LONG NewData;
NewData = ((struct StringInfo *)Gadget->SpecialInfo)->LongInt;
if ((NewData < 1L) || (NewData > Max)) {
GT_SetGadgetAttrs(Gadget, BlankerWindow, NULL, GTIN_Number, (ULONG) * Data,
TAG_DONE);
return FALSE;
} else {
*Data = NewData;
return TRUE;
}
}
void
CloseBlankerWindow(void)
{
if (BlankerWindow) {
/*
* We save the current position of the window
* so it will re-open in the same place, later.
*/
NewBlankerWindow.LeftEdge = BlankerWindow->LeftEdge;
NewBlankerWindow.TopEdge = BlankerWindow->TopEdge;
RemTool(BlankerGadgets);
RemTool(BlankerVisualInfo);
RemTool(BlankerWindow);
BlankerWindow = NULL;
}
}
void
OpenBlankerWindow(void)
{
struct Gadget *Ptr;
UWORD Index;
static char Title[80];
if (BlankerWindow == NULL) {
strcpy(Title, "REyes = <");
strcat(Title, PopKey);
strcat(Title, ">");
if (BlankerWindow = OpenWindowTags(&NewBlankerWindow, WA_Title, Title,
WA_AutoAdjust, TRUE, WA_InnerWidth,
212, WA_InnerHeight, 118, TAG_DONE)) {
AddTool(BlankerWindow, CloseWindow, NULL,"Could not open the window.");
if ((BlankerVisualInfo = GetVisualInfo(BlankerWindow->WScreen, TAG_DONE))
== NULL) {
RemTool(BlankerWindow);
return;
}
AddTool(BlankerVisualInfo, FreeVisualInfo, 0L,
"Couldn't get visual data.");
BlankerGadgets = NULL;
if ((Ptr = CreateContext(&BlankerGadgets)) == NULL) {
RemTool(BlankerVisualInfo);
RemTool(BlankerWindow);
return;
}
AddTool(Ptr, FreeGadgets, 0L,"Couldn't allocate the gadgets.");
/* Here we re-load the gadgets with the current settings. */
TimeGadgetTags[0].ti_Data = (ULONG) TimeOut;
ClientGadgetTags[0].ti_Data = (ULONG) ClientTimeOut;
SpeedGadgetTags[0].ti_Data = (ULONG) Speed;
SpeedGadgetTags[3].ti_Data = (ULONG) "%2ld";
#ifndef SMALLEYES
ChanceGadgetTags[0].ti_Data = (ULONG) Chance;
ChanceGadgetTags[3].ti_Data = (ULONG) "%3ld";
#endif
EyesGadgetTags[0].ti_Data = (ULONG) NumEyes;
EyesGadgetTags[3].ti_Data = (ULONG) "%2ld";
for (Index = 0L; Index < NUM_GADS; Index++) {
NewBlankerGadgets[Index].ng_TopEdge += BlankerWindow->BorderTop;
NewBlankerGadgets[Index].ng_VisualInfo = BlankerVisualInfo;
Ptr = CreateGadgetA((ULONG) BlankerGadgetKinds[Index], Ptr,
&NewBlankerGadgets[Index],
BlankerGadgetTagLists[Index]);
if (Ptr == NULL) {
CloseBlankerWindow();
return;
}
NewBlankerGadgets[Index].ng_TopEdge -= BlankerWindow->BorderTop;
}
AddGList(BlankerWindow, BlankerGadgets, 0L, -1L, NULL);
RefreshGadgets(BlankerGadgets, BlankerWindow, NULL);
GT_RefreshWindow(BlankerWindow, NULL);
}
}
ScreenToFront(BlankerWindow->WScreen);
WindowToFront(BlankerWindow);
ActivateWindow(BlankerWindow);
}
/*
* Function to handle the Commodity Stuff
*/
void __regargs
HandleCxMsg(CxObj * Broker, CxMsg * CxMsg, LONG * TimeUntilBlank,
LONG * ThisTimeOut)
{
ULONG MsgType, MsgID;
MsgType = CxMsgType(CxMsg);
MsgID = CxMsgID(CxMsg);
ReplyMsg((struct Message *)CxMsg);
switch (MsgType) {
case CXM_IEVENT: /* a hotkey was pressed */
switch (MsgID) {
case HOTKEY_OPEN_WINDOW:
OpenBlankerWindow();
break;
case HOTKEY_BLANK_SCREEN:
if (*TimeUntilBlank)
*TimeUntilBlank = *ThisTimeOut = 2L;
}
case CXM_COMMAND:
switch (MsgID) {
case CXCMD_DISABLE: /* Message from Exchange
* (except CXCMD_UNIQUE) */
(void)ActivateCxObj(Broker, FALSE);
break;
case CXCMD_ENABLE:
(void)ActivateCxObj(Broker, TRUE);
break;
case CXCMD_UNIQUE:
case CXCMD_APPEAR:
OpenBlankerWindow();
break;
case CXCMD_DISAPPEAR:
CloseBlankerWindow();
break;
case CXCMD_KILL:
Quit(0,"Normal Termination.");
}
}
}
#ifdef OBSOLETE
/*
* These functions have been replaced by defines.
* They're provided here for hysterical raisins.
*/
void
SpritesOff(struct RetinaScreen *rs)
{
struct TagItem tags[] =
{RSP_On, 0L, TAG_DONE, 0L};
Retina_SpriteFunction(rs, tags);
}
void
SpritesOn(struct RetinaScreen *rs)
{
struct TagItem tags[] =
{RSP_On, 1L, TAG_DONE, 0L};
Retina_SpriteFunction(rs, tags);
}
#else
/*
* We use defines for these functions just to pick up a little speed.
*/
#define SpritesOff(rs) \
{ \
struct TagItem tags[] = \
{RSP_On, 0L, TAG_DONE, 0L}; \
\
Retina_SpriteFunction(rs, tags);\
}
#define SpritesOn(rs) \
{ \
struct TagItem tags[] = \
{RSP_On, 1L, TAG_DONE, 0L}; \
\
Retina_SpriteFunction(rs, tags);\
}
#endif
/*
* This, annoyingly enough, is neccessary because Retina_CloseScreen is
* actually a #pragma and not a real function call. This means you
* can't pass a pointer to Retina_CloseScreen as a function argument
* to AddTool. By adding this wrapper function, we make AddTool work.
*/
void
DestroyScreen(struct RetinaScreen *rs)
{
Retina_CloseScreen(rs);
}
/*
* Create Screen will first attempt to open a "normal" resolution screen.
* If that fails, it will try opening a lower resolution screen.
* If that fails it will return NULL.
*/
struct RetinaScreen *
CreateScreen(void)
{
struct RetinaScreen *Screen;
if (!(Screen = Retina_OpenScreen(NORMAL_WIDE, NORMAL_HIGH, MID_DEFAULT_08,
RSFF_DOUBLEBUFFER, NULL)))
if (!(Screen = Retina_OpenScreen(SMALL_WIDE, SMALL_HIGH, MID_DEFAULT_08,
RSFF_DOUBLEBUFFER, NULL)))
return NULL;
Retina_LoadPalette(Screen, 0, EYES_COLS, color_table);
SpritesOff(Screen);
return Screen;
}
/*
* Functions for Creating/Deleting the Client Process
*/
void __stdargs
DeleteBlankerClient(struct MsgPort * ClientPort)
{
struct ClientMessage ClientMessage;
/* Send the terminating message to the client.
* We kick up the client's priority to ensure a
* prompt response.
*/
Forbid();
ClientMessage.bcm_Message.mn_ReplyPort = FINDPROCPORT;
PutMsg(ClientPort, (struct Message *)&ClientMessage);
(void)SetTaskPri(ClientPort->mp_SigTask, SERVER_PRI);
Permit();
/* Get the response. */
(void)WaitPort(ClientMessage.bcm_Message.mn_ReplyPort);
(void)GetMsg(ClientMessage.bcm_Message.mn_ReplyPort);
}
struct MsgPort *__regargs
CreateBlankerClient(void *ClientRoutine, struct ClientMessage *ClientMessage)
{
struct Process *ClientProcess;
struct TagItem ProcTags[3];
ProcTags[0].ti_Tag = NP_Entry;
ProcTags[0].ti_Data = (ULONG) ClientRoutine;
ProcTags[1].ti_Tag = NP_Name;
ProcTags[1].ti_Data = (ULONG) "ClientProcess";
ProcTags[2].ti_Tag = TAG_DONE;
if (ClientProcess = CreateNewProc(ProcTags)) {
ClientMessage->bcm_Message.mn_ReplyPort = FINDPROCPORT;
PutMsg(&ClientProcess->pr_MsgPort, (struct Message *)ClientMessage);
(void)WaitPort(ClientMessage->bcm_Message.mn_ReplyPort);
(void)GetMsg(ClientMessage->bcm_Message.mn_ReplyPort);
(void)SetTaskPri((struct Task *)ClientProcess, CLIENT_PRI);
if (ClientMessage->bcm_Status)
return &ClientProcess->pr_MsgPort;
}
return NULL;
}
/*
* Functions for Creating/Drawing/Removing the Eyes
*/
LONG __inline
Insure1(LONG val)
{
return ((val == 0) ? 1 : val); /* return value that is at least 1 */
}
/*
* This is a fairly high-speed psuedo random number generator,
* but it's not to random, though. Occasionally, it will
* be non-random enough for a while to cause all the Eyes to
* move in the same direction (or some such.) I use it
* because it's fast and because, with all the collision
* detection done now, it's less likely the un-randomness
* will be noticed.
*/
WORD __regargs
Random(WORD Max)
{
static ULONG Num = 0L;
ULONG Sec, Mic;
CurrentTime((ULONG *) & Sec, (ULONG *) & Mic);
Num *= Sec;
Num += Mic;
while (Num > 32767L)
Num = Num >> 1;
return (WORD)(Num % Max);
}
/*
* Free up the list of eyes.
*/
void __regargs
DeleteEyes(EyeStruct *EyeList)
{
LONG i;
for (i=0;i<EyeList->NumEyes;i++)
if (EyeList->Eye[i]!=NULL) FreeMem(EyeList->Eye[i],sizeof(Eyes));
}
/*
* Create the list of eyes.
*/
EyeStruct *__regargs
CreateEyes(struct RetinaScreen *Screen,
LONG NumEyes, LONG Speed)
{
int Index, i, flag, count;
Eyes *randomeyes[4];
if (!Screen) return NULL;
randomeyes[0]=&BlueEyes;
randomeyes[1]=&GreenEyes;
randomeyes[2]=&VioletEyes;
randomeyes[3]=&BrownEyes;
/*
* Create the Eyes
*/
for (Index = 0; Index < NumEyes; Index++) {
if (!(EyeList.Eye[Index]=AllocMem(sizeof(Eyes),MEMF_PUBLIC|MEMF_CLEAR)))
Quit(20,"Out of Memory!!!");
CopyMem(randomeyes[Random(4)],EyeList.Eye[Index],sizeof(Eyes));
#ifndef SMALLEYES
EyeList.Eye[Index]->currentframe=Random(EyeList.Eye[Index]->maxframes);
#else
EyeList.Eye[Index]->currentframe=0;
#endif
EyeList.Eye[Index]->xspeed=Insure1(RAND(Speed));
EyeList.Eye[Index]->yspeed=Insure1(RAND(Speed));
count=0; flag=1;
/*
* We try 4 times to fit an eye pair on the screen. If we can't, then
* the screen must be too small for the # of eyes and we truncate the list.
*/
while (flag & count<4) {
EyeList.Eye[Index]->xpos=Random(Screen->rs_Width-
EyeList.Eye[Index]->width);
EyeList.Eye[Index]->ypos=Random(Screen->rs_Height-
EyeList.Eye[Index]->height);
flag=0;
for (i=0;i<Index; i++) {
/* Looking for overlapping rectangles... */
if ((EyeList.Eye[i]->xpos>
EyeList.Eye[Index]->xpos-EyeList.Eye[i]->width)&&
(EyeList.Eye[i]->xpos<
EyeList.Eye[Index]->xpos+EyeList.Eye[Index]->width)&&
(EyeList.Eye[i]->ypos>
EyeList.Eye[Index]->ypos-EyeList.Eye[i]->height)&&
(EyeList.Eye[i]->ypos<
EyeList.Eye[Index]->ypos+EyeList.Eye[Index]->height)) {
flag=1;
break;
}
}
}
if (flag) { /* If we failed to add an Eye pair, truncate the list. */
NumEyes=Index+1;
break;
}
}
EyeList.NumEyes=NumEyes;
return &EyeList;
}
/* move the Eyes and redraw them */
void __regargs
DrawEyes(EyeStruct *EyeList, struct RetinaScreen *rs, LONG Chance)
{
int Index,i;
Eyes **EL;
/*
* This assignment provides a (very mild) speed up buy removing
* one level of indirection from all the work that's going on below.
*/
EL=EyeList->Eye;
Chance=Insure1(100-Chance);
/* If we don't have a screen, don't draw on it! (duh.) */
if (!rs) return;
for (Index=0; Index<EyeList->NumEyes; Index++) {
/* Move the Eye. */
EL[Index]->old_xpos=EL[Index]->xpos;
EL[Index]->old_ypos=EL[Index]->ypos;
EL[Index]->xpos+=EL[Index]->xspeed;
EL[Index]->ypos+=EL[Index]->yspeed;
/* Bounce check */
if (EL[Index]->xpos<0) {
EL[Index]->xpos=0;
EL[Index]->xspeed=Insure1(RAND(Speed));
} else if (EL[Index]->xpos>rs->rs_Width-EL[Index]->width-1) {
EL[Index]->xpos=rs->rs_Width-EL[Index]->width-1;
EL[Index]->xspeed=Insure1(RAND(Speed));
}
if (EL[Index]->ypos<0) {
EL[Index]->ypos=0;
EL[Index]->yspeed=Insure1(RAND(Speed));
} else if (EL[Index]->ypos>rs->rs_Height-EL[Index]->height-1) {
EL[Index]->ypos=rs->rs_Height-EL[Index]->height-1;
EL[Index]->yspeed=Insure1(RAND(Speed));
}
/*
* Collision check...
* If we detect that we hit one other eye pair, we reverse direction.
* Note - checking stops after the first collision, otherwise
* multiple-collisions might cause the eye pair to continue in
* the same direction (i.e., its direction got negated twice)
*/
for (i=0;i<EyeList->NumEyes; i++) {
if (i!=Index) {
if ((EL[i]->xpos>EL[Index]->xpos-EL[i]->width)&&
(EL[i]->xpos<EL[Index]->xpos+EL[Index]->width)&&
(EL[i]->ypos>EL[Index]->ypos-EL[i]->height)&&
(EL[i]->ypos<EL[Index]->ypos+EL[Index]->height)) {
EL[Index]->yspeed= (EL[Index]->yspeed>0)?-Insure1(Random(Speed/2)):Insure1(Random(Speed/2));
EL[Index]->xspeed= (EL[Index]->xspeed>0)?-Insure1(Random(Speed/2)):Insure1(Random(Speed/2));
EL[Index]->xpos=EL[Index]->old_xpos;
EL[Index]->ypos=EL[Index]->old_ypos;
break;
}
}
}
#ifndef SMALLEYES
/* Are we animating this Eye pair? */
if (EL[Index]->currentframe) {
if (!EL[Index]->tic) {
EL[Index]->tic++;
} else {
EL[Index]->tic=0;
EL[Index]->currentframe=(EL[Index]->currentframe+1)%
EL[Index]->maxframes;
}
/* No? Then roll the dice and see if we should start... */
} else if (!Random(Chance)) {
EL[Index]->currentframe=1;
}
#endif
}
/* Redraw on the background bitmap... */
for (Index=0; Index<EyeList->NumEyes; Index++) {
Retina_WriteRect(EL[Index]->animtable[EL[Index]->currentframe],
0,0,
EL[Index]->width, RECTMODE_256,
rs,EL[Index]->xpos, EL[Index]->ypos,
EL[Index]->width, EL[Index]->height, NULL);
}
/* Swap the bitmaps */
Retina_SwapBitMap(rs);
/* Erase the old images on the new background bitmap. */
for (Index=0; Index<EyeList->NumEyes; Index++) {
Retina_RectFill(rs,EL[Index]->old_xpos,
EL[Index]->old_ypos,
EL[Index]->old_xpos+EL[Index]->width,
EL[Index]->old_ypos+EL[Index]->height);
}
}
/*
* This is the Client Process's Main Loop
*/
void __interrupt __saveds
REyesClientProcess(void)
{
struct ClientMessage *ClientMessage;
struct MsgPort *ClientPort;
struct Task *ServerTask;
ULONG ServerSigMask;
struct RetinaScreen *EyesScreen;
LONG NumEyes, Speed, Chance;
EyeStruct *EyeList;
/* wait for Server's initial Message */
ClientPort = FINDPROCPORT;
(void)WaitPort(ClientPort);
ClientMessage = (struct ClientMessage *)GetMsg(ClientPort);
ServerTask = ClientMessage->bcm_Message.mn_ReplyPort->mp_SigTask;
ServerSigMask = ClientMessage->bcm_SigMask;
NumEyes = ClientMessage->bcm_Eyes;
Speed = ClientMessage->bcm_Speed;
Chance = ClientMessage->bcm_Chance;
EyesScreen = ClientMessage->bcm_Screen;
if (EyesScreen) {
if ((EyeList = CreateEyes(EyesScreen, NumEyes, Speed))== NULL) {
ClientMessage->bcm_Status = FALSE;
Forbid();
ReplyMsg((struct Message *)ClientMessage);
return;
}
}
ClientMessage->bcm_Status = TRUE;
ReplyMsg((struct Message *)ClientMessage);
/* Animate the blanker screen until a termination message is received. */
while ((ClientMessage = (struct ClientMessage *)GetMsg(ClientPort)) == NULL) {
if (EyesScreen) DrawEyes(EyeList, EyesScreen, Chance);
/*
* We signal the server after each loop so it will know that we're alive.
*/
Signal(ServerTask, ServerSigMask);
}
/* We are requested to finish, so we do. */
if (EyeList) DeleteEyes(EyeList);
Forbid();
ReplyMsg((struct Message *)ClientMessage);
}
/*
* The Main Loop
*/
void
main(LONG argc, UBYTE * argv[])
{
char **ToolTypes;
CxObj *Broker, *ObjectList, *Filter;
struct IntuiMessage *IntMsg;
CxMsg *BlankerCxMsg;
LONG ThisTimeOut, TimeUntilBlank, TimeUntilBlack;
struct RetinaScreen *BlankerScreen = NULL;
struct MsgPort *ClientPort = NULL;
int BlankFlag=0;
/* open our Libraries */
AddTool(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",
37L), CloseLibrary, 0L,
"Couldn't open the intuition.library.");
AddTool(IconBase = OpenLibrary("icon.library", 37L), CloseLibrary, 0L,
"Couldn't open the icon library.");
AddTool(CxBase = OpenLibrary("commodities.library", 37L), CloseLibrary, 0L,
"Couldn't open the commoidities library.");
AddTool(GadToolsBase = OpenLibrary("gadtools.library", 37L), CloseLibrary, 0L,
"Couldn't open the gadtools library.");
AddTool(RetinaBase = (struct _xy_RetinaBase *)OpenLibrary("retina.library", 7L),
CloseLibrary, 0L,"Couldn't open the Retina library.");
/* get our Arguments */
if (ToolTypes = ArgArrayInit(argc, argv))
AddTool(ToolTypes, ArgArrayDone, 0L,NULL);
/* get some Signals */
ServerProcess = SysBase->ThisTask;
if ((bsp_TimerSig = AllocSignal(-1L)) == -1)
Quit(10,"Could not allocate a signal.");
AddTool((void *)bsp_TimerSig, FreeSignal, 0L,NULL);
if ((bsp_InputSig = AllocSignal(-1L)) == -1)
Quit(10,"Could not allocate a signal.");
AddTool((void *)bsp_InputSig, FreeSignal, 0L,NULL);
if ((bsp_ClientSig = AllocSignal(-1L)) == -1)
Quit(10,"Could not allocate a signal.");
AddTool((void *)bsp_ClientSig, FreeSignal, 0L,NULL);
/* initialize our Broker = install us as a Commodity */
AddTool(CxPort = CreateMsgPort(), DeleteMsgPortSafely, 0L,
"Failed to create a port.");
NewBroker.nb_Descr=&VersionString[6];
NewBroker.nb_Pri = ArgInt(ToolTypes, "CX_PRIORITY", DEF_CX_PRI);
NewBroker.nb_Port = CxPort;
AddTool(Broker = CxBroker(&NewBroker, NULL), DeleteCxObjAll, 0L,
NULL);
/* get Time Out, Client Time Out and Display mode */
TimeOut = ArgIntMax(ToolTypes, "TIMEOUT", DEF_TIMEOUT, MAX_TIMEOUT);
ClientTimeOut = ArgIntMax(ToolTypes, "CLIENTTIMEOUT", DEF_CLIENT_TIMEOUT,
MAX_CLIENT_TIMEOUT);
/* get Parameters for Eye Movement */
NumEyes = ArgIntMax(ToolTypes, "EYES", DEF_EYES, MAX_EYES);
Speed = ArgIntMax(ToolTypes, "SPEED", DEF_SPEED, MAX_SPEED);
Chance = ArgIntMax(ToolTypes, "%ANIM", DEF_CHANCE, MAX_CHANCE);
/* install our hot keys */
PopKey = ArgString(ToolTypes, "CX_POPKEY", DEF_POPKEY);
BlankKey = ArgString(ToolTypes, "BLANKKEY", DEF_BLANKKEY);
if ((Filter = HotKey(PopKey, CxPort, HOTKEY_OPEN_WINDOW)) == NULL)
Quit(10,"The CX_POPKEY tool type is invalid.");
else
AttachCxObj(Broker, Filter);
if (CxObjError(Filter))
Quit(10,"Could not link to the commodity list.");
if ((Filter = HotKey(BlankKey, CxPort, HOTKEY_BLANK_SCREEN)) == NULL)
Quit(10,"The BLANKKEY tool type is invalid.");
else
AttachCxObj(Broker, Filter);
if (CxObjError(Filter))
Quit(10,"Could not link to the commodity list.");
/* install our "InputHandler" */
ObjectList = CxCustom(BlankerAction, 0L);
AttachCxObj(Broker, ObjectList);
if (CxObjError(ObjectList))
Quit(10,"Could not link to the commodity list.");
(void)ActivateCxObj(Broker, TRUE);
AddTool(Broker, ActivateCxObj, 0L,"The broker broke.");
/* open Window on startup if not forbidden */
if (stricmp(ArgString(ToolTypes, "CX_POPUP", ""), "NO"))
OpenBlankerWindow();
/*
* increase our Priority
* Note that when we quit, our priority will be reset to what it
* was before.
*/
AddTool(FindTask(NULL), SetTaskPri, (LONG) SetTaskPri(FindTask(NULL), SERVER_PRI),
"Findtask failed!");
/* start the Loop */
TimeUntilBlank = ThisTimeOut = 10L * TimeOut;
TimeUntilBlack = 10L * ClientTimeOut;
FOREVER
{
ULONG Mask;
if (BlankerWindow)
Mask = Wait(MASK(bsp_TimerSig) | MASK(bsp_InputSig) | MASK(bsp_ClientSig) |
MASK(CxPort->mp_SigBit) |
MASK(BlankerWindow->UserPort->mp_SigBit) |
SIGBREAKF_CTRL_C);
else
Mask = Wait(MASK(bsp_TimerSig) | MASK(bsp_InputSig) | MASK(bsp_ClientSig) |
MASK(CxPort->mp_SigBit) | SIGBREAKF_CTRL_C);
/* process Window Events */
while ((BlankerWindow != NULL) && (IntMsg =
GT_GetIMsg(BlankerWindow->UserPort)))
switch (IntMsg->Class) {
struct Gadget *Clicked;
UWORD Code;
case IDCMP_CLOSEWINDOW:
GT_ReplyIMsg(IntMsg);
CloseBlankerWindow();
break;
case IDCMP_REFRESHWINDOW:
GT_BeginRefresh(BlankerWindow);
GT_EndRefresh(BlankerWindow, TRUE);
break;
case IDCMP_GADGETUP:
Code = IntMsg->Code;
Clicked = (struct Gadget *)IntMsg->IAddress;
GT_ReplyIMsg(IntMsg);
switch (Clicked->GadgetID) {
case GID_HIDE:
CloseBlankerWindow();
break;
case GID_QUIT:
Quit(0,"Normal Termination.");
case GID_BLANK:
TimeUntilBlank = ThisTimeOut = 2L;
break;
case GID_TIMEOUT:
if (GetNum(Clicked, &TimeOut, MAX_TIMEOUT))
TimeUntilBlank = ThisTimeOut = 10L * TimeOut;
break;
case GID_CLIENT:
if (GetNum(Clicked, &ClientTimeOut, MAX_CLIENT_TIMEOUT))
TimeUntilBlack = 10L * ClientTimeOut;
break;
case GID_EYES:
NumEyes = Code;
break;
case GID_SPEED:
Speed = Code;
break;
case GID_CHANCE:
Chance = Code;
break;
}
break;
case IDCMP_VANILLAKEY:
Code = IntMsg->Code;
GT_ReplyIMsg(IntMsg);
switch ((char)Code) {
case 'H':
case 'h':
CloseBlankerWindow();
break;
case 'Q':
case 'q':
Quit(0,"Normal Termination.");
case 'B':
case 'b':
TimeUntilBlank = ThisTimeOut = 2L;
}
break;
default:
GT_ReplyIMsg(IntMsg);
}
/* process Commodity Messages */
while (BlankerCxMsg = (CxMsg *) GetMsg(CxPort))
HandleCxMsg(Broker, BlankerCxMsg, &TimeUntilBlank, &ThisTimeOut);
/* check for <CTRL>-C */
if (Mask & SIGBREAKF_CTRL_C)
Quit(0,"Normal Termination.");
/* Input detected, unblank if necessary */
if (Mask & MASK(bsp_InputSig)) {
if (BlankFlag) {
if (ClientPort)
RemTool(ClientPort);
if (BlankerScreen) {
SpritesOn(BlankerScreen);
RemTool(BlankerScreen);
} else
Retina_DisplayOn();
BlankFlag=0;
ThisTimeOut = 10L * TimeOut;
}
TimeUntilBlank = ThisTimeOut;
}
/* client has confirmed that it is still alive */
if (Mask & MASK(bsp_ClientSig)) {
if (BlankerScreen) Retina_DisplayOn();
TimeUntilBlack = 10L * ClientTimeOut;
BlankFlag=1;
}
/* 1/10 sec is over */
if (Mask & MASK(bsp_TimerSig))
if (TimeUntilBlank) {
TimeUntilBlank--;
if (TimeUntilBlank == 0L) { /* Time Out reached, blank
* the screen */
struct ClientMessage ClientMessage;
BlankFlag=1;
BlankerScreen=CreateScreen();
if (BlankerScreen)
AddTool(BlankerScreen, DestroyScreen, 0L,NULL);
else
/* do this if we're completely out of video memory. */
Retina_DisplayOff();
ClientMessage.bcm_Screen = BlankerScreen;
ClientMessage.bcm_SigMask = 1L << bsp_ClientSig;
ClientMessage.bcm_Eyes = NumEyes;
ClientMessage.bcm_Speed = Speed;
ClientMessage.bcm_Chance = Chance;
if (ClientPort = CreateBlankerClient(REyesClientProcess,
&ClientMessage)) {
TimeUntilBlack = 10L * ClientTimeOut;
/* try to start Client */
AddTool(ClientPort, DeleteBlankerClient, 0L,NULL);
}
}
} else {
if ((BlankerScreen)&&(RetinaBase->rb_FirstScreen != BlankerScreen)) {
Retina_ScreenToFront(BlankerScreen);
SpritesOff(BlankerScreen);
}
if (TimeUntilBlack) {
TimeUntilBlack--;
if (TimeUntilBlack == 0L)
Retina_DisplayOff(); /* Client Time Out
* reached, turn entire
* screen black */
}
}
}
}